# @Author : Labyrinthine Leo
# @Time   : 2020.11.24
# @problem: ZDT2
# Benchmark MOP proposed by Zitzler, Deb, and Thiele
################################## Reference ################################
# E. Zitzler, K. Deb, and L. Thiele, Comparison of multiobjective           #
# evolutionary algorithms: Empirical results, Evolutionary computation,     #
# 2000, 8(2): 173-195.                                                      #
#############################################################################

import numpy as np
import platgo as pg


class ZDT2(pg.Problem):

    def __init__(self, D: int = 30) -> None:
        self.name = "ZDT2"
        self.type['multi'], self.type['real'], self.type['large'], self.type['expensive'] = [True] * 4
        self.M = 2
        self.D = D
        lb = [0] * self.D
        ub = [1] * self.D
        self.borders = np.array([lb, ub])
        super().__init__()

    def cal_obj(self, pop: pg.Population) -> None:
        decs = pop.decs
        pop.cv = np.zeros((pop.N, self.D))
        g = 1 + 9*np.mean(decs[:, 1:], axis=1, keepdims=True)
        h = 1 - np.square(decs[:, 0:1]/g)
        pop.objv = np.hstack((decs[:, 0:1], g*h))

    def get_optimal(self) -> np.ndarray:
        N = 10000  # 生成10000个参考点
        ObjV1 = np.linspace(0, 1, N)
        ObjV2 = 1 - ObjV1 ** 2
        referenceObjV = np.array([ObjV1, ObjV2]).T
        return referenceObjV

if __name__ == '__main__':
    z = ZDT2(D=5)
    pop = pg.Population(decs=np.random.uniform(0, 1, (10, 5)))
    print(z.borders)
    print(pop.decs)
    z.cal_obj(pop) # 计算目标函数值
    print(pop.objv)

